#include "VConsole.h"

#include <Windows.h>
#include <process.h>
#include <iostream>
#include <concrt.h>
#include "defs.h"

using std::cout;
using std::endl;
using std::string;

bool VConsole::stop = true;
VConsole::VConsole(void)
{

}


VConsole::~VConsole(void)
{
}

void VConsole::Write( const string &message, CONSOLE_COLOR color ) const
{
    //SYSTEMTIME time;
    //GetLocalTime ( &time );
    //std::cout << time.wHour << ":" << time.wMinute << ":" << time.wSecond << ": " << message << std::endl;

    HANDLE hConsole;
    hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
    SetConsoleTextAttribute( hConsole, color );

    cout << message << endl;

    SetConsoleTextAttribute( hConsole, WHITE );
}

void VConsole::Write( const string &preMessage, const string &postMessage, CONSOLE_COLOR color ) const
{
    HANDLE hConsole;
    hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
    
    cout << preMessage << "  [";
     
    SetConsoleTextAttribute( hConsole, color );

    cout << postMessage;

    SetConsoleTextAttribute( hConsole, WHITE );

    cout << "]" << endl;
}

void VConsole::Write( const string &message, const int num ) const
{
    cout << message << num << endl;
}

//TODO: find new decision
unsigned __stdcall VConsole::WriteWaiting( void *message )
{
    char *args = (char*)message;
    string printingMess = args;

    while ( stop )
    {
        cout << '\r';
        cout << printingMess;   Sleep(250);//Concurrency::wait (250);
        cout << ".";            Sleep(250);//Concurrency::wait (250);
        cout << ".";            Sleep(250);//Concurrency::wait (250);
        cout << ".";            Sleep(250);//Concurrency::wait (250);
        cout << '\r';
        ClearString();
    }
    cout << "\r";   

    return 0;
}

void VConsole::WriteMenuItemOut( string &message )
{
/*
 *  X(t) = Xo + Vo * t + a * t^2 / 2;
 *  | t = j;
 *  | Xo = 0; - start caret's position
 *  | Vo = 1; - start caret's speed
 *  | a = 1; - caret's speed-up
 */

    double pos = 0;
    int time = 0;
  
    while ( pos <= CONSOLE_STRING_LENGTH )
    {
        //move caret to the right
        cout.width( pos );
        
        //print message
        cout << message;
        
        //wait 50 ms
        Concurrency::wait(50);
        
        //return caret to the beginnig of the line
        cout <<"\r";
        
        //pos = 
        time++;
        pos = time * CONSOLE_CARET_SPEED + CONSOLE_CARET_SPEEDUP * time * time / 2;
    }
}

void VConsole::WriteMenuItemIn( string &message )
{
    double pos = CONSOLE_STRING_LENGTH - 1;
    int time = 0;

    while ( pos >= 0 )
    {
        //clear line
        ClearString();

        //move caret to the right
        cout.width( pos );
        
        //print message
        cout << message;
        
        //wait 50 ms
        Concurrency::wait(50);
        
        //return caret to the beginnig of the line
        cout <<"\r";
        
        //pos = 
        time++;
        pos = CONSOLE_STRING_LENGTH - time * CONSOLE_CARET_SPEED - CONSOLE_CARET_SPEEDUP * time * time / 2;
    }
}

void VConsole::WriteProgressBar( int size, float step )
{
/*
 <#######             >
*/
    for ( int i = 0; i < size; i+= step )
    {
        std::cout << "#";
        Concurrency::wait(50);
    }
}

//TODO: find new decision!!! this is bad
void VConsole::ClearString()
{
    string cleaner;

    cleaner.reserve( CONSOLE_STRING_LENGTH );
    for ( int i = 0; i < CONSOLE_STRING_LENGTH - 1; i++ )
        cleaner += " ";

    cout << "\r" << cleaner << "\r";
}

void VConsole::WrWait( string &message, int number )
{
    char *messageArg[2];
    char *ff = new char[10];
    messageArg[0] = const_cast<char*>( message.c_str() );
    itoa( number, ff, 10 );
    messageArg[1] = ff;
    unsigned uThreadID;

    HANDLE hThread;

    hThread = (HANDLE)_beginthreadex( NULL, 0, &(VConsole::WriteWaiting), messageArg , 0, &uThreadID);

    WaitForSingleObject( hThread, INFINITE );
     
    CloseHandle( hThread );
}
